package com.xuewei.pagedemo.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.util.ReflectionUtils;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class BeansUtil {

	/**
	 * 拷贝属性
	 */
	public static <T> T copyProperties(Object source, T target) {
		try {
			BeanUtils.copyProperties(source, target);
		} catch (BeansException e) {
			log.error("copy properties error ", e);
			handleReflectionException(e);
		}
		return target;
	}

	/**
	 * 拷贝属性,忽略null值
	 * @param source
	 * @param target
	 */
	public static <T> T copyPropertiesIgnoreNull(Object source, T target){
		try {
			BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
		} catch (BeansException e) {
			log.error("copy properties error ", e);
			handleReflectionException(e);
		}
		return target;
	}
	
	/**
	 * 转换Bean对象
	 */
	public static <T> T convert(Object source, Class<T> tClass) {
		T t = null;
		try {
			t = tClass.newInstance();
			if (source == null) {
//				return t;
				return null;
			}
			BeanUtils.copyProperties(source, t);
		} catch (Exception e) {
			log.error("tClass convert error ", e);
			handleReflectionException(e);
		}
		return t;
	}

	/**
	 * 转换List对象
	 */
	public static <T> List<T> convert(List<?> source, Class<T> tClass) {
		List<T> result = new ArrayList<T>();
		try {
			for (Object o : source) {
				if (o != null) {
					T t = tClass.newInstance();
					BeanUtils.copyProperties(o, t);
					result.add(t);
				}
			}
		} catch (Exception e) {
			log.error("List convert error ", e);
			handleReflectionException(e);
		}
		return result;
	}
	
//	private static BeanUtilsBean b = BeanUtilsBean.getInstance();
//
//	public static Object cloneBean(Object bean){
//		try {
//			return b.cloneBean(bean);
//		} catch (Exception e) {
//			handleReflectionException(e);
//			return null;
//		}
//	}


	private static String[] getNullPropertyNames (Object source) {
		final BeanWrapper src = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = src.getPropertyDescriptors();

		Set<String> emptyNames = new HashSet<String>();
		for(PropertyDescriptor pd : pds) {
			Object srcValue = src.getPropertyValue(pd.getName());
			if (srcValue == null) {
				emptyNames.add(pd.getName());
			}
		}
		String[] result = new String[emptyNames.size()];
		return emptyNames.toArray(result);
	}

	private static void handleReflectionException(Exception e) {
		ReflectionUtils.handleReflectionException(e);
	}

}
